using System;
using System.Diagnostics;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
using NUnit.Framework;

namespace UniAspect.UnitTests
{
    [TestFixture]
    public class DynamicProxyPerformance
    {
        /// <summary>
        /// Performance test that shouldn't be run regularly
        /// </summary>
        //[Test]
        public void RelativeToSimpleCalls()
        {
            var regularStopwatch = new Stopwatch();
            var instance = new SomeProxyTarget();
            ISomeProxyTarget target = instance;
            var tries = 1000000;

            Console.WriteLine("Tries: {0,-16}", tries);

            regularStopwatch.Start();
            for(int i = 0; i < tries; i++)
            {
                target.DoSomething(i, 2);
            }
            regularStopwatch.Stop();

            Console.WriteLine();
            PrintResults("Regular", regularStopwatch, tries);

            var generator = new ProxyGenerator();

            target = generator.CreateInterfaceProxyWithTarget<ISomeProxyTarget>(
                    instance, new SimpleInterceptor());

            var proxiedStopwatch = new Stopwatch();
            proxiedStopwatch.Start();
            for(int i = 0; i < tries; i++)
            {
                target.DoSomething(i, 2);
            }
            proxiedStopwatch.Stop();

            Console.WriteLine();
            PrintResults("Proxied", proxiedStopwatch, tries);

            Console.WriteLine();
            PrintComparison(regularStopwatch, proxiedStopwatch);
        }

        public interface ISomeProxyTarget
        {
            int DoSomething(int a, int b);
        }

        public class SomeProxyTarget : ISomeProxyTarget
        {
            public int DoSomething(int a, int b)
            {
                return a + b;
            }
        }

        public class SimpleInterceptor : IInterceptor
        {
            public void Intercept(IInvocation invocation)
            {
                invocation.Proceed();
            }
        }

        protected void PrintComparison(Stopwatch regular, Stopwatch proxied)
        {
            Console.WriteLine("Relative : {0,12} ms/ms,  {1,18} ticks/ticks",
                              (double)proxied.ElapsedMilliseconds / regular.ElapsedMilliseconds,
                              (double)proxied.ElapsedTicks / regular.ElapsedTicks);
        }

        protected void PrintResults(string header, Stopwatch stopwatch, int tries)
        {
            Console.WriteLine(header);
            Console.WriteLine("Overall  : {0,12} ms,      {1,18} ticks",
                              stopwatch.ElapsedMilliseconds,
                              stopwatch.ElapsedTicks);
            Console.WriteLine("Per call : {0,12} ms/call, {1,18} ticks/call",
                              (double)stopwatch.ElapsedMilliseconds / tries,
                              (double)stopwatch.ElapsedTicks / tries);
        }
    }
}